#ifndef __OLED_H__
#define __OLED_H__

#include <basic.h>

/*
Attention 使用dma的时候要开启iiC event 中断
*/

#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_ADDR (0x3c << 1)
#define I2C_TIMEOUT_MS (10)

#define OLED_CMD 0                   // 写命令
#define OLED_DATA 1                  // 写数据
#define OLED_PAGES (OLED_HEIGHT / 8) // 8

class oled
{
public:
    /*
        scan direction is
    */
    void drawBitmap(uint8_t sx, uint8_t sy, uint8_t w, uint8_t h, const uint8_t *bitmap, const size_t bitmap_size, uint8_t color = 1);
    void fillRectangle(uint8_t sx, uint8_t sy, uint8_t w, uint8_t h, uint8_t color = 1);

    /*
        经测定，iic 400kHz条件下,不启用DMA 刷新一次大约需要25ms左右
                                启用DMA后 调用一次仅仅需要1ms
    */
    void refresh();
    void clear();
    void fullscreen(uint8_t color);
    void init();
    I2C_HandleTypeDef *get_i2c() { return i2c; };
    static oled &instance();

private:
    I2C_HandleTypeDef *i2c;
    bool should_refresh = false;
    uint8_t oled_buffer[OLED_WIDTH * OLED_PAGES]; // 1KB
    uint8_t dma_buffer[1024 + 1];

    oled(I2C_HandleTypeDef *i2c) : i2c(i2c) {};
    void write_byte(uint8_t dat, uint8_t mode);

    /*
        经测定，如果一个点一个点调用的话，调用128*64次要花12~13ms
    */
    void drawPixel(uint8_t x, uint8_t y, uint8_t color = 1);
    void setByte(uint8_t x, uint8_t page, uint8_t byte, uint8_t start_bit = 0, uint8_t write_len = 8);

    oled(const oled &) = delete;
    oled &operator=(const oled &) = delete;
};

void oled_test_software();

#endif
